#ifndef REGISTERVIEW_HPP
#define REGISTERVIEW_HPP

#include <QDockWidget>
#include <QTableWidgetItem>
#include <QTimer>
#include <QMap>
#include <QBrush>
#include <QMapIterator>
#include <QDebug>
#include <QThread>
#include <math.h>

#include "register.hpp"

namespace Ui {
    class RegisterView;
}

/**
* @brief
*
* @class RegisterView registerview.hpp "registerview.hpp"
*/
class RegisterView : public QDockWidget {
    Q_OBJECT
public:
    /**
    * @brief Constructor for RegisterView
    *
    * @fn RegisterView(QWidget *parent = 0)
    * @param parent
    */
    RegisterView(QWidget *parent = 0);

    /**
    * @brief Destructor for RegisterView
    *
    * @fn ~RegisterView()
    */
    ~RegisterView();

    /**
    * @brief Activates or deactivates highlighting
    *
    * @fn void setHighlighting(bool state)
    * @param state
    */
    void setHighlighting(bool state);

    int getValue(int bank, int address);

protected:
    /**
    * @brief Action on ChangeEvent
    *
    * @fn void changeEvent(QEvent *e)
    * @param e
    */
    void changeEvent(QEvent *e);

private:
    Ui::RegisterView *ui;
    QMap<int, QTableWidgetItem*> itemsBank0;
    QMap<int, QTableWidgetItem*> itemsBank1;
    QMap<QTableWidgetItem*, QTimer*> changedTimerMap;
    QMap<int, bool> itemChanged;
    bool initializing;
    bool highlightingState;

    /**
    * @brief Initialize the Bank TableView
    *
    * @fn void initializeView()
    */
    void initializeView();

    /**
    * @brief Sets the timer to unhighlight a widget
    *
    * @fn void setTimer(QTableWidgetItem *item)
    * @param item
    */
    void setTimer(QTableWidgetItem *item);

public slots:
    /**
    * @brief Slot is called when the internal data of an Register changed
    *
    * @fn Q_INVOKABLE void onRegisterChanged(Register *reg)
    * @param reg
    */
    Q_INVOKABLE void onRegisterChanged(Register *reg);

    /**
    * @brief Slot is called when the Bank has been changed by the program
    *
    * @fn void onBankChanged(bool bank)
    * @param bank
    */
    void onBankChanged(bool bank);

    /**
    * @brief Slot is called when programCounter has been changed
    *
    * @fn void onProgramCounterChanged(int programCounter)
    * @param programCounter
    */
    void onProgramCounterChanged(int programCounter);

private slots:
    /**
    * @brief The content of a Cell has changed
    * @details Update the internal Register data to this value
    *
    * @fn void on_tbl_bank0_cellChanged(int row, int column)
    * @param row
    * @param column
    */
    void on_tbl_bank0_cellChanged(int row, int column);

    /**
    * @brief The content of a Cell has changed
    * @details Update the internal Register data to this value
    *
    * @fn void on_tbl_bank1_cellChanged(int row, int column)
    * @param row
    * @param column
    */
    void on_tbl_bank1_cellChanged(int row, int column);

    /**
    * @brief Triggered when user doubleclicks on a cell in bank0
    *
    * @fn void on_tbl_bank0_cellDoubleClicked(int row, int column)
    * @param row
    * @param column
    */
    void on_tbl_bank0_cellDoubleClicked(int row, int column);

    /**
    * @brief Triggered when user doubleclicks on a cell in bank1
    *
    * @fn void on_tbl_bank1_cellDoubleClicked(int row, int column)
    * @param row
    * @param column
    */
    void on_tbl_bank1_cellDoubleClicked(int row, int column);

    /**
    * @brief Slot triggered when the Timer expires
    *
    * @fn void onChangedTimerExpires()
    */
    void onChangedTimerExpires();

    /**
    * @brief Slot triggered when Port A Bits checked or unchecked
    *
    * @fn void onCbPortaStateChanged()
    */
    void onCbPortaStateChanged();

    /**
    * @brief Slot triggered when Port B Bits checked or unchecked
    *
    * @fn void onCbPortbStateChanged()
    */
    void onCbPortbStateChanged();

    /**
    * @brief Slot triggered when Tris A Bits checked or unchecked
    *
    * @fn void onCbTrisaStateChanged()
    */
    void onCbTrisaStateChanged();

    /**
    * @brief Slot triggered when Tris B Bits checked or unchecked
    *
    * @fn void onCbTrisbStateChanged()
    */
    void onCbTrisbStateChanged();

    /**
    * @brief Slot Triggered when Bit 5 of status register is checked or unchecked
    *
    * @fn void on_cb_status_5_clicked()
    */
    void on_cb_status_5_clicked();

signals:
    /**
    * @brief Signal is emitted to request a change of the data of an Register
    *
    * @fn void requestChangeRegister(int address, int value)
    * @param address
    * @param value
    */
    void requestChangeRegister(int address, int value);

    /**
    * @brief Signal is emitted to request a bank switch
    *
    * @fn void requestChangeBank(bool bank)
    * @param bank
    */
    void requestChangeBank(bool bank);
};

#endif // REGISTERVIEW_HPP
